"use strict";

import { app, protocol, BrowserWindow, ipcMain, dialog, shell } from "electron";
import { createProtocol } from "vue-cli-plugin-electron-builder/lib";
import installExtension, { VUEJS3_DEVTOOLS } from "electron-devtools-installer";
import path from "path";
import { exec } from "child_process";
import http from "http";
import fs from "fs";
import os from "os";
import { spawn } from "child_process";
import fetch from "node-fetch";
import axios from "axios";
import { promisify } from "util";
import { wechatApi, messageListener } from "./services/apiService";

const isDevelopment = process.env.NODE_ENV !== "production";

// 创建一个简单的日志记录函数
function logMessage(message) {
  console.log(`[主进程日志] ${message}`);
  // 如果有活动窗口，可以将日志发送到渲染进程
  const windows = BrowserWindow.getAllWindows();
  if (windows.length > 0) {
    windows[0].webContents.send("log-message", message);
  }
}

// 为 wechatApi 设置主进程专用的日志函数
// 这样在主进程中使用 wechatApi 时就不会尝试访问 window 对象
wechatApi._logToConsole = function (message) {
  logMessage(message);
};

// 为 messageListener 设置主进程专用的日志函数
// 这样在主进程中使用 messageListener 时就不会尝试访问 window 对象
messageListener._logToConsole = function (message) {
  logMessage(message);
};

// 全局存储 HTTP 服务器实例
let messageServer = null;

// 全局变量，用于跟踪已注册的IPC处理程序
const registeredHandlers = new Set();

// Scheme must be registered before the app is ready
protocol.registerSchemesAsPrivileged([
  { scheme: "app", privileges: { secure: true, standard: true } },
]);

// 将exec转换为Promise版本
const execAsync = promisify(exec);

async function createWindow() {
  // Create the browser window.
  const win = new BrowserWindow({
    width: 1200,
    height: 800,
    webPreferences: {
      // Use pluginOptions.nodeIntegration, leave this alone
      // See nklayman.github.io/vue-cli-plugin-electron-builder/guide/security.html#node-integration for more info
      nodeIntegration: process.env.ELECTRON_NODE_INTEGRATION,
      contextIsolation: !process.env.ELECTRON_NODE_INTEGRATION,
      preload: path.join(__dirname, "preload.js"),
    },
  });

  if (process.env.WEBPACK_DEV_SERVER_URL) {
    // Load the url of the dev server if in development mode
    await win.loadURL(process.env.WEBPACK_DEV_SERVER_URL);
    if (!process.env.IS_TEST) win.webContents.openDevTools();
  } else {
    createProtocol("app");
    // Load the index.html when not in development
    win.loadURL("app://./index.html");
  }

  // 处理外部链接
  win.webContents.setWindowOpenHandler(({ url }) => {
    shell.openExternal(url);
    return { action: "deny" };
  });

  return win;
}

// 安全地注册IPC处理程序的辅助函数
function safelyRegisterHandler(channel, handler) {
  if (registeredHandlers.has(channel)) {
    console.log(`处理程序 '${channel}' 已经注册，跳过重复注册`);
    return;
  }

  ipcMain.handle(channel, handler);
  registeredHandlers.add(channel);
  logMessage(`已注册处理程序: ${channel}`);
}

// 获取注入工具路径
safelyRegisterHandler("get-inject-tool-path", (event) => {
  const platform = process.platform;
  let toolPath = "";

  if (platform === "win32") {
    // Windows
    toolPath = path.join(process.resourcesPath, "resources", "inject_tool.exe");
  } else if (platform === "darwin") {
    // macOS
    toolPath = path.join(process.resourcesPath, "resources", "inject_tool");
  } else {
    // Linux 或其他平台
    toolPath = path.join(process.resourcesPath, "resources", "inject_tool");
  }

  console.log("注入工具路径:", toolPath);
  return toolPath;
});

// 检查文件是否存在
safelyRegisterHandler("check-file-exists", async (event, filePath) => {
  try {
    await fs.promises.access(filePath, fs.constants.F_OK);
    return { exists: true };
  } catch (error) {
    return { exists: false, error: error.message };
  }
});

// 注入微信
safelyRegisterHandler("inject-wechat", async (event, options) => {
  const { injectToolPath, dllPort, msgPort } = options;
  return await executeInjection(injectToolPath, dllPort, msgPort, event);
});

// 执行注入逻辑
async function executeInjection(toolPath, dllPort, msgPort, event) {
  // 组装命令行命令
  let command = "";
  const platform = process.platform;

  // 检查在macOS上是否尝试运行.exe文件
  if (platform === "darwin" && toolPath.toLowerCase().endsWith(".exe")) {
    event.sender.send("injection-error", {
      error: "在macOS系统中无法直接执行.exe文件，请使用适用于macOS的可执行文件",
    });
    console.error("在macOS系统上尝试执行Windows .exe文件:", toolPath);
    return {
      success: false,
      error: "在macOS系统中无法直接执行.exe文件，请使用适用于macOS的可执行文件",
    };
  }

  // 检查注入工具是否存在
  try {
    await fs.promises.access(toolPath, fs.constants.F_OK);
    console.log("注入工具存在:", toolPath);
  } catch (error) {
    console.error("注入工具不存在:", toolPath, error);

    // 尝试在其他可能的位置查找
    const alternativePaths = [];

    if (platform === "win32") {
      // Windows系统的可能路径
      alternativePaths.push(
        path.join(
          app.getAppPath(),
          "resources",
          "resources",
          "inject_tool.exe"
        ),
        path.join(app.getAppPath(), "resources", "inject_tool.exe"),
        path.join(process.resourcesPath, "resources", "inject_tool.exe"),
        path.join(process.resourcesPath, "inject_tool.exe"),
        "C:\\inject_tool.exe"
      );
    } else if (platform === "darwin") {
      // macOS系统的可能路径
      alternativePaths.push(
        path.join(app.getAppPath(), "resources", "resources", "inject_tool"),
        path.join(app.getAppPath(), "resources", "inject_tool"),
        path.join(process.resourcesPath, "resources", "inject_tool"),
        path.join(process.resourcesPath, "inject_tool"),
        path.join(os.homedir(), "inject_tool")
      );
    } else {
      // Linux系统的可能路径
      alternativePaths.push(
        path.join(app.getAppPath(), "resources", "resources", "inject_tool"),
        path.join(app.getAppPath(), "resources", "inject_tool"),
        path.join(process.resourcesPath, "resources", "inject_tool"),
        path.join(process.resourcesPath, "inject_tool"),
        path.join(os.homedir(), "inject_tool")
      );
    }

    // 检查替代路径
    let foundPath = null;
    for (const altPath of alternativePaths) {
      try {
        await fs.promises.access(altPath, fs.constants.F_OK);
        console.log("在替代路径找到注入工具:", altPath);
        foundPath = altPath;
        break;
      } catch (err) {
        // 继续检查下一个路径
      }
    }

    if (!foundPath) {
      return {
        success: false,
        error: `注入工具不存在: ${toolPath}`,
      };
    }

    toolPath = foundPath;
  }

  // 根据操作系统构建命令
  if (platform === "win32") {                                                                                                                          
    // Windows - 使用正确的命令格式
    command = `"${toolPath}" start ${dllPort} --my_port ${msgPort}`;
  } else {
    // 其他平台不支持，返回错误
    logMessage("注入工具仅支持 Windows 平台");
    return {
      success: false,
      error: "注入工具仅支持 Windows 平台",
    };
  }

  logMessage(`执行命令: ${command}`);

  // 执行命令
  return new Promise((resolve) => {
    exec(command, async (error, stdout, stderr) => {
      logMessage(`命令执行结果 - stdout: ${stdout}`);
      logMessage(`命令执行结果 - stderr: ${stderr}`);

      if (error) {
        logMessage(`命令执行错误: ${error}`);
        event.sender.send("injection-error", { error: error.message });
        resolve({ success: false, error: error.message });
        return;
      }

      if (stderr && stderr.trim() !== "") {
        logMessage(`命令执行stderr: ${stderr}`);
      }

      // 发送注入输出到渲染进程
      event.sender.send("injection-output", {
        type: "stdout",
        content: stdout,
      });

      // 尝试从输出中提取实际端口
      const actualPorts = extractPortsFromOutput(stdout);
      logMessage(`实际端口: ${JSON.stringify(actualPorts)}`);
    //   if (actualPorts.dllPort && actualPorts.dllPort !== dllPort) {
    //     logMessage(
    //       `注意: 实际DLL端口(${actualPorts.dllPort})与请求的端口(${dllPort})不同`
    //     );

    //     // 发送端口更新事件
    //     event.sender.send("port-update", {
    //       requestedDllPort: dllPort,
    //       actualDllPort: actualPorts.dllPort,
    //       requestedMsgPort: msgPort,
    //       actualMsgPort: actualPorts.msgPort || msgPort,
    //     });

    //     // 使用实际端口进行登录状态检查
    //     startLoginStatusCheck(actualPorts.dllPort, event);
    //   } else {
    //     // 使用请求的端口进行登录状态检查
    //     startLoginStatusCheck(dllPort, event);
    //   }

      resolve({ success: true ,actualPorts});
    });
  });
}

// 从注入工具输出中提取实际端口
function extractPortsFromOutput(output) {
  const result = { dllPort: null, msgPort: null };

  try {
    // 尝试匹配中文输出中的端口号
    // 例如: "עɹDLL˿ںΪ8918 | Ķ˿ںΪ9000"
    const dllPortMatch = output.match(/DLL.*?(\d+)/);
    const msgPortMatch = output.match(/.*?(\d+)$/);

    if (dllPortMatch && dllPortMatch[1]) {
      result.dllPort = parseInt(dllPortMatch[1]);
    }

    if (msgPortMatch && msgPortMatch[1]) {
      result.msgPort = parseInt(msgPortMatch[1]);
    }

    logMessage(
      `从输出中提取的端口: DLL端口=${result.dllPort}, 消息端口=${result.msgPort}`
    );
  } catch (error) {
    logMessage(`提取端口时出错: ${error.message}`);
  }

  return result;
}

// 检查登录状态的函数
async function startLoginStatusCheck(port, event) {
  let checkCount = 0;
  const maxCheckCount = 40; // 最多检查40次，约2分钟

  logMessage(`开始检查登录状态，端口: ${port}`);

  const checkInterval = setInterval(async () => {
    try {
      checkCount++;

      // 使用 API 检查登录状态
      const loginStatus = await checkLoginStatusViaAPI(port);

      // 发送登录状态到渲染进程
      event.sender.send("login-status-update", {
        count: checkCount,
        maxCount: maxCheckCount,
        ...loginStatus,
      });

      // 如果已登录或者达到最大检查次数，停止检查
      if (loginStatus.isLoggedIn || checkCount >= maxCheckCount) {
        clearInterval(checkInterval);
        logMessage(
          `登录状态检查结束: ${loginStatus.isLoggedIn ? "已登录" : "未登录"}`
        );
      }
    } catch (error) {}
  }, 3000); // 每3秒检查一次

  // 设置超时，防止无限检查
  setTimeout(() => {
    if (checkInterval) {
      clearInterval(checkInterval);
      logMessage("登录状态检查超时");
      event.sender.send("login-status-update", {
        count: maxCheckCount,
        maxCount: maxCheckCount,
        isLoggedIn: false,
        reason: "检查超时",
      });
    }
  }, 120000); // 2分钟超时
}

// 通过 API 检查登录状态
async function checkLoginStatusViaAPI(port) {
  try {
    // 记录实际使用的端口
    logMessage(`尝试检查登录状态，使用端口: ${port}`);

    // 设置 API 端口
    wechatApi.setPort(port);

    // 使用 wechatApi 获取登录状态
    const data = await wechatApi.getLoginStatus();
    logMessage(`登录状态API响应: ${JSON.stringify(data)}`);

    // 根据API文档，status为1表示已登录
    const isLoggedIn = data.errno === 0 && data.data && data.data.status === 1;

    return {
      isLoggedIn,
      reason: isLoggedIn ? "已登录" : "未登录",
      apiResponse: data,
    };
  } catch (error) {
    logMessage(`API检查登录状态出错: ${error.message}`);

    // 如果是连接被拒绝错误，尝试使用注入工具输出的端口
    if (error.message.includes("ECONNREFUSED")) {
      // 尝试从错误消息中提取实际端口
      const portMatch = error.message.match(/127\.0\.0\.1:(\d+)/);
      const attemptedPort = portMatch ? portMatch[1] : null;

      logMessage(
        `连接被拒绝，尝试的端口: ${attemptedPort}，配置的端口: ${port}`
      );

      // 如果端口不匹配，建议用户检查配置
      if (attemptedPort && attemptedPort !== port.toString()) {
        return {
          isLoggedIn: false,
          reason: `端口不匹配: 尝试连接 ${attemptedPort}，但配置的是 ${port}，请检查注入工具输出的实际端口`,
        };
      }
    }

    return {
      isLoggedIn: false,
      reason: `检查出错: ${error.message}`,
    };
  }
}

// 启动消息监听服务
safelyRegisterHandler("start-listening", async (event, options) => {
  try {
    // 处理参数，支持直接传入端口号或包含端口的对象
    let port = 9000; // 默认端口
    if (typeof options === "number") {
      port = options;
    } else if (options && options.port) {
      port = options.port;
    }

    console.log(`开始在端口 ${port} 上监听消息...`);

    // 如果已有服务器在运行，先停止
    if (messageServer) {
      await stopServer();
    }

    // 创建新的 HTTP 服务器
    messageServer = http.createServer((req, res) => {
      // 设置 CORS 头，允许跨域请求
      res.setHeader("Access-Control-Allow-Origin", "*");
      res.setHeader("Access-Control-Allow-Methods", "POST, OPTIONS");
      res.setHeader("Access-Control-Allow-Headers", "Content-Type");

      // 处理 OPTIONS 请求（预检请求）
      if (req.method === "OPTIONS") {
        res.writeHead(204);
        res.end();
        return;
      }

      // 只处理 POST 请求和 /msg 路径
      if (req.method === "POST" && req.url === "/msg") {
        let body = "";

        req.on("data", (chunk) => {
          body += chunk.toString();
        });

        req.on("end", () => {
          try {
            // 尝试解析消息体为 JSON
            let message;
            try {
              message = JSON.parse(body);
            } catch (e) {
              // 如果不是有效的 JSON，保持原样
              message = body;
            }

            // 向渲染进程发送消息
            event.sender.send("message-received", message);

            // 返回成功响应
            res.writeHead(200, { "Content-Type": "application/json" });
            res.end(JSON.stringify({ status: "success" }));
          } catch (error) {
            console.error("处理消息时出错:", error);

            // 返回错误响应
            res.writeHead(500, { "Content-Type": "application/json" });
            res.end(
              JSON.stringify({
                status: "error",
                message: `处理消息时出错: ${error.message}`,
              })
            );
          }
        });
      } else {
        // 对于其他请求，返回 404
        res.writeHead(404, { "Content-Type": "application/json" });
        res.end(
          JSON.stringify({ status: "error", message: "未找到请求的资源" })
        );
      }
    });

    // 使用 Promise 包装服务器启动过程
    return new Promise((resolve, reject) => {
      // 设置超时，防止服务器启动卡住
      const timeout = setTimeout(() => {
        reject(new Error(`启动消息监听服务超时，端口: ${port}`));
      }, 5000);

      // 监听错误
      messageServer.on("error", (err) => {
        clearTimeout(timeout);
        console.error(`启动消息监听服务失败:`, err);
        reject(err);
      });

      // 开始监听
      messageServer.listen(port, () => {
        clearTimeout(timeout);
        console.log(`消息监听服务已启动，端口: ${port}`);
        resolve({ success: true, port: port });
      });
    });
  } catch (error) {
    console.error("启动消息监听服务时出错:", error);
    return { success: false, error: error.message };
  }
});

// 停止服务器的辅助函数
async function stopServer() {
  return new Promise((resolve, reject) => {
    if (!messageServer) {
      console.log("没有正在运行的服务器");
      resolve();
      return;
    }

    messageServer.close((err) => {
      if (err) {
        console.error("关闭服务器错误:", err);
        reject(err);
        return;
      }

      console.log("服务器已关闭");
      messageServer = null;
      resolve();
    });
  });
}

// 获取资源路径
safelyRegisterHandler("get-resources-path", () => {
  return process.resourcesPath;
});

// 获取当前工作目录
safelyRegisterHandler("get-current-dir", () => {
  const currentDir = process.cwd();
  console.log("当前工作目录:", currentDir);
  return currentDir;
});

// 获取操作系统信息
ipcMain.handle("get-os-info", () => {
  const platform = os.platform();
  const release = os.release();
  const arch = os.arch();
  const info = `${platform} ${release} (${arch})`;
  console.log("操作系统信息:", info);
  return info;
});

// 打开URL
safelyRegisterHandler("open-url", async (event, url) => {
  console.log("打开URL:", url);
  try {
    // 使用默认浏览器打开URL
    await shell.openExternal(url);
    return { success: true };
  } catch (error) {
    console.error("打开URL异常:", error);
    return { success: false, error: error.message };
  }
});

// 停止消息监听服务
safelyRegisterHandler("stop-listening", async () => {
  try {
    await stopServer();
    return { success: true };
  } catch (error) {
    console.error("停止消息监听服务时出错:", error);
    return { success: false, error: error.message };
  }
});

// 选择文件
safelyRegisterHandler("select-file", async (event, options) => {
  const result = await dialog.showOpenDialog({
    title: options.title || "选择文件",
    defaultPath: options.defaultPath,
    filters: options.filters,
    properties: ["openFile"],
  });

  return {
    canceled: result.canceled,
    filePath: result.filePaths[0],
  };
});

// 检查微信是否已登录（不使用API接口）
async function checkWeChatLoginStatus(event) {
  logMessage("检查微信是否已登录");
}

// 注册检查微信登录状态的IPC处理程序
safelyRegisterHandler("check-wechat-login-status", checkWeChatLoginStatus);

// 打开开发者工具
function openDevTools(event) {
  const windows = BrowserWindow.getAllWindows();
  if (windows.length > 0) {
    windows[0].webContents.openDevTools();
    return { success: true };
  }
  return { success: false, error: "没有可用的窗口" };
}

// Quit when all windows are closed.
app.on("window-all-closed", () => {
  // On macOS it is common for applications and their menu bar
  // to stay active until the user quits explicitly with Cmd + Q
  if (process.platform !== "darwin") {
    app.quit();
  }
});

app.on("activate", () => {
  // On macOS it's common to re-create a window in the app when the
  // dock icon is clicked and there are no other windows open.
  if (BrowserWindow.getAllWindows().length === 0) createWindow();
});

// This method will be called when Electron has finished
// initialization and is ready to create browser windows.
// Some APIs can only be used after this event occurs.
app.whenReady().then(async () => {
  if (isDevelopment && !process.env.IS_TEST) {
    // Install Vue Devtools
    try {
      await installExtension(VUEJS3_DEVTOOLS);
    } catch (e) {
      console.error("Vue Devtools failed to install:", e.toString());
    }
  }

  // 所有 IPC 处理程序已经在其他地方注册，这里不需要重复注册

  createWindow();
  safelyRegisterHandler("open-dev-tools", openDevTools);
});

// Exit cleanly on request from parent process in development mode.
if (isDevelopment) {
  if (process.platform === "win32") {
    process.on("message", (data) => {
      if (data === "graceful-exit") {
        app.quit();
      }
    });
  } else {
    process.on("SIGTERM", () => {
      app.quit();
    });
  }
}

// 退出前停止服务器
app.on("before-quit", () => {
  // 使用 Promise 而不是 await
  stopServer().catch((err) => {
    console.error("退出前停止服务器失败:", err);
  });
});
